package com.yanqu.road.server.manager.marriage;

import com.yanqu.road.entity.enums.eMarriageStatusType;
import com.yanqu.road.entity.marriage.MarriageInfo;
import com.yanqu.road.entity.union.cross.CrossUnionServerGroup;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.MarriagePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.marriage.CrossMarriageProto;
import com.yanqu.road.pb.marriage.MarriageProto;
import com.yanqu.road.server.TempCrossMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manger.CrossUnionServerGroupMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 本服联姻(跨服商会分组内)
 */
public class CrossUnionWorldMarriageMgr extends TempCrossMgr {

    private static Logger logger = LogManager.getLogger(CrossUnionWorldMarriageMgr.class.getName());

    private static RandomHelper randomHelper = new RandomHelper();

    private static Object lock = new Object();


    private static List<Long> uploadServerList = new ArrayList<>();

    /**
     * 子嗣编号，子嗣数据
     */
    private static Map<String, MarriageInfo> allMarriageMap = new ConcurrentHashMap<>();

    /**
     * 服务器，子嗣编号，子嗣数据
     */
    private static Map<Long, Map<String, MarriageInfo>> serverMarriageMap = new ConcurrentHashMap<>();

    //缓存玩家的本服列表
    //userId sexType
    private static Map<Long, Map<Integer, Map<String, MarriageInfo>>> userServerApplyMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    /**
     * 取消发布
     */
    public static int cancelPublish(long serverId, long userId, String childUid){
        synchronized (lock){
            MarriageInfo marriageInfo = allMarriageMap.remove(childUid);
            if(marriageInfo != null){
                //tmp,其他查询是没有锁的
                marriageInfo.setStatus(eMarriageStatusType.WAIT);
            }
            Map<String, MarriageInfo> map = serverMarriageMap.get(serverId);
            if(map != null){
                map.remove(childUid);
            }
        }
        return 0;
    }

    /**
     * 发布请求
     * @param serverId 区服
     * @param marriageInfo 联姻请求
     */
    public static void publish(long serverId, MarriageInfo marriageInfo) {
        int ret = 0;
        synchronized (lock){
            if(!serverMarriageMap.containsKey(serverId)){
                serverMarriageMap.put(serverId, new ConcurrentHashMap<>());
            }
            allMarriageMap.put(marriageInfo.getChildUid(), marriageInfo);
            serverMarriageMap.get(serverId).put(marriageInfo.getChildUid(), marriageInfo);
        }

        CrossMarriageProto.CrossMarriageApplyPublishCrossRespMsg.Builder respMsg = CrossMarriageProto.CrossMarriageApplyPublishCrossRespMsg.newBuilder();
        respMsg.setRet(ret);
        respMsg.setChildUid(marriageInfo.getChildUid());
        respMsg.setPublishTime(marriageInfo.getPublishTime());
        MessageHelper.sendPacket(serverId, marriageInfo.getUserId(), YanQuMessageUtils.buildMessage(Protocol.S_CROSS_WORLD_MARRIAGE_PUBLISH_RESP, respMsg));
    }


    /**
     * 上报全服联姻请求
     * @param serverId 区服
     * @param marriageInfoList 联姻请求
     */
    public static void upload(long serverId, List<MarriageInfo> marriageInfoList) {
        logger.info("CrossUnionWorldMarriage , 数据上报，区服：{}，大小：{}", serverId, marriageInfoList.size());
        synchronized (lock){
            if(marriageInfoList.size() == 0){
                uploadServerList.add(serverId);
                return;
            }
            if(!serverMarriageMap.containsKey(serverId)){
                serverMarriageMap.put(serverId, new ConcurrentHashMap<>());
            }
            Map<String, MarriageInfo> tempMap = new HashMap<>();
            for (MarriageInfo marriageInfo : marriageInfoList) {
                tempMap.put(marriageInfo.getChildUid(), marriageInfo);
            }
            serverMarriageMap.get(serverId).putAll(tempMap);
            allMarriageMap.putAll(tempMap);
            uploadServerList.add(serverId);
        }
    }

    /**
     * 获取全服联姻列表, 随机获取5个
     */
    public static List<MarriageInfo> getServerApplyList(long userId, long serverId, int childSex) {
        List<MarriageInfo> applyList = new ArrayList<>();
        if(userServerApplyMap.containsKey(userId)) {
            Map<Integer, Map<String, MarriageInfo>> userApplyMap = userServerApplyMap.get(userId);
            if(userApplyMap.containsKey(childSex)) {
                Map<String, MarriageInfo> sexApplyMap = userApplyMap.get(childSex);
                for (MarriageInfo marriageInfo : sexApplyMap.values()) {
                    if (marriageInfo.getStatus() != eMarriageStatusType.CrossWorldPublish || isOverApplyTime(marriageInfo) ||
                            !allMarriageMap.containsKey(marriageInfo.getChildUid())) {//过期或者已联姻的移除掉
                        sexApplyMap.remove(marriageInfo.getChildUid());
                    }
                }
                applyList.addAll(sexApplyMap.values());
            }
        }
        if(applyList.size() <= 0){
            applyList = refreshServerApplyList(userId, serverId, childSex);
        }
        return applyList;
    }

    /**
     * 刷新全服联姻列表, 随机获取5个
     */
    public static List<MarriageInfo> refreshServerApplyList(long userId, long serverId, int childSex) {
        List<MarriageInfo> applyList = new ArrayList<>();
        if(!userServerApplyMap.containsKey(userId)) {
            userServerApplyMap.put(userId, new ConcurrentHashMap<>());
        }
        Map<Integer, Map<String, MarriageInfo>> userApplyMap = userServerApplyMap.get(userId);
        if(!userApplyMap.containsKey(childSex)){
            userApplyMap.put(childSex, new ConcurrentHashMap<>());
        }
        Map<String, MarriageInfo> sexApplyMap = userApplyMap.get(childSex);
        //过滤分组
        List<MarriageInfo> tempList = getAllMarriageByServerId(serverId);
        sexApplyMap.clear();

        while (true) {
            if (tempList.size() > 0) {
                int randomNum = randomHelper.next(0, tempList.size());
                MarriageInfo marriageInfo = tempList.get(randomNum);
                if (marriageInfo.getUserId() != userId && marriageInfo.getStatus() == eMarriageStatusType.CrossWorldPublish &&
                        marriageInfo.getChildSex() != childSex && !isOverApplyTime(marriageInfo)) {

                    applyList.add(marriageInfo);
                    sexApplyMap.put(marriageInfo.getChildUid(), marriageInfo);

                }
                tempList.remove(randomNum);
            } else {
                break;
            }
            if (applyList.size() >= GameConfig.MARRIAGE_MAX_SEVER_APPLY_LIST_COUNT) {
                break;
            }
        }
        return applyList;
    }

    /**
     * 分组内发布的联姻
     */
    private static List<MarriageInfo> getAllMarriageByServerId(long serverId) {
        int groupId = CrossUnionServerGroupMgr.getGroupIdByServerId(serverId);
        Set<Long> serverSet = CrossUnionServerGroupMgr.getGroupServer(groupId);
        Map<String, MarriageInfo> allMap = new HashMap<>();
        for (long sid : serverSet) {
            Map<String, MarriageInfo> serverMap = serverMarriageMap.get(sid);
            if(serverMap != null){
                allMap.putAll(serverMap);
            }
        }
        return new ArrayList<>(allMap.values());
    }

    /**
     * 发布时间是否超时
     */
    private static boolean isOverApplyTime(MarriageInfo marriageInfo) {
        return System.currentTimeMillis()/1000 - marriageInfo.getPublishTime() > GameConfig.MARRIAGE_PUBLISH_TIME;
    }

    /**
     * 发起联姻
     */
    public static void agreeMarriage(long serverId, long userId, String partnerChildUid, MarriageProto.MarriageApplyTempMsg myMarriage) {
        MarriageInfo partnerMarriage = allMarriageMap.get(partnerChildUid);
        if(partnerMarriage == null){
            //返回状态错误
            sendErrorCodeBack(myMarriage);
            return;
        }
        synchronized (lock){
            partnerMarriage = allMarriageMap.remove(partnerChildUid);
            if(partnerMarriage == null){
                //返回状态错误
                sendErrorCodeBack(myMarriage);
            }else {
                //取消对方，联姻是否有条件？
                cancelPublish(partnerMarriage.getServerId(), partnerMarriage.getUserId(), partnerChildUid);

                CrossMarriageProto.CrossMarriageAgreeCrossDealReqMsg.Builder dealMsg = CrossMarriageProto.CrossMarriageAgreeCrossDealReqMsg.newBuilder();
                dealMsg.setApplyData(myMarriage);
                dealMsg.setPartnerChildUid(partnerChildUid);
                YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_WORLD_MARRIAGE_AGREE_REQ, dealMsg);
                MessageHelper.sendPacket(partnerMarriage.getServerId(), partnerMarriage.getUserId(), pbMsg);
            }
        }
    }

    public static void sendErrorCodeBack(MarriageProto.MarriageApplyTempMsg myMarriage) {
        CrossMarriageProto.CrossMarriageAgreeCrossDealRespMsg.Builder respMsg = CrossMarriageProto.CrossMarriageAgreeCrossDealRespMsg.newBuilder();
        respMsg.setRet(GameErrorCode.E_MARRIAGE_CHILD_NO_FOUND);
        respMsg.setApplyData(myMarriage);
        MarriageInfo marriageInfo = MarriagePb.parseMarriageInfo(myMarriage);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_WORLD_MARRIAGE_AGREE_RESP, respMsg);
        MessageHelper.sendPacket(marriageInfo.getServerId(), marriageInfo.getUserId(), pbMsg);
    }

    public static void checkServerUpload() {
        int channelId = ConfigHelper.getInt("channelId");
        for (CrossUnionServerGroup serverGroup : CrossUnionServerGroupMgr.getServerGroupList(channelId)) {
            if(serverGroup.getState() == 1){
                for (long sid : serverGroup.getServerList()) {
                    if(uploadServerList.contains(sid)){
                        continue;
                    }
                    logger.info("send to server {} upload marriage info", sid);
                    CrossMarriageProto.CrossWorldMarriageUploadNotifyMsg.Builder notify = CrossMarriageProto.CrossWorldMarriageUploadNotifyMsg.newBuilder();
                    MessageHelper.sendPacket(sid, 0, YanQuMessageUtils.buildMessage(Protocol.S_CROSS_WORLD_MARRIAGE_NOTIFY_UPLOAD, notify));
                }
            }
        }
    }


    @Override
    public boolean removeExpireData() throws Exception {
        return true;
    }
}
